{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "#!python\n",
    "%matplotlib inline\n",
    "from __future__ import print_function\n",
    "import time\n",
    "\n",
    "import numpy as np\n",
    "from numpy import convolve as np_convolve\n",
    "from scipy.signal import fftconvolve, lfilter, firwin\n",
    "from scipy.signal import convolve as sig_convolve\n",
    "from scipy.ndimage import convolve1d\n",
    "import matplotlib.pyplot as plt"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "ename": "TypeError",
     "evalue": "convolve() missing 1 required positional argument: 'v'",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mTypeError\u001b[0m                                 Traceback (most recent call last)",
      "\u001b[0;32m<ipython-input-3-3892f89bf76f>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[1;32m     28\u001b[0m     \u001b[0;31m# --- numpy.convolve ---\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     29\u001b[0m     \u001b[0mtstart\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mtime\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mtime\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 30\u001b[0;31m     \u001b[0mnpconv_result\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mnp_convolve\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mnp_convolve\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mxi\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mb\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mmode\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m'valid'\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mxi\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mx\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m     31\u001b[0m     \u001b[0mnpconv_time\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mappend\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mtime\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mtime\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;34m-\u001b[0m \u001b[0mtstart\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     32\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;31mTypeError\u001b[0m: convolve() missing 1 required positional argument: 'v'"
     ]
    }
   ],
   "source": [
    "# Create the m by n data to be filtered.\n",
    "m = 1\n",
    "n = 2 ** 18\n",
    "x = np.random.random(size=(m, n))\n",
    "\n",
    "conv_time = []\n",
    "npconv_time = []\n",
    "fftconv_time = []\n",
    "conv1d_time = []\n",
    "lfilt_time = []\n",
    "\n",
    "diff_list = []\n",
    "diff2_list = []\n",
    "diff3_list = []\n",
    "\n",
    "ntaps_list = 2 ** np.arange(2, 14)\n",
    "\n",
    "for ntaps in ntaps_list:\n",
    "    # Create a FIR filter.\n",
    "    b = firwin(ntaps, [0.05, 0.95], width=0.05, pass_zero=False)\n",
    "    \n",
    "    # --- signal.convolve ---\n",
    "    # 这里就是将信号和 FIR 滤波器卷积\n",
    "    tstart = time.time()\n",
    "    conv_result = sig_convolve(x, b[np.newaxis, :], mode='valid')\n",
    "    conv_time.append(time.time() - tstart)\n",
    "    \n",
    "    # --- numpy.convolve ---\n",
    "    tstart = time.time()\n",
    "    npconv_result = np.array([np_convolve(xi, b, mode='valid') for xi in x])\n",
    "    npconv_time.append(time.time() - tstart)\n",
    "    \n",
    "    # --- signal.fftconvolve ---\n",
    "    tstart = time.time()\n",
    "    fftconv_result = fftconvolve(x, b[np.newaxis, :], mode='valid')\n",
    "    fftconv_time.append(time.time() - tstart)\n",
    "    \n",
    "    # --- convolve1d ---\n",
    "    tstart = time.time()\n",
    "    # convolve1d doesn't have a 'valid' mode, so we expliclity slice out\n",
    "    # the valid part of the result.\n",
    "    conv1d_result = convolve1d(x, b)[:, (len(b)-1)//2 : -(len(b)//2)]\n",
    "    conv1d_time.append(time.time() - tstart)\n",
    "    \n",
    "    # --- lfilter --- \n",
    "    tstart = time.time()\n",
    "    lfilt_result = lfilter(b, [1.0], x)[:, len(b) - 1:]\n",
    "    lfilt_time.append(time.time() - tstart)\n",
    "    \n",
    "    diff = np.abs(fftconv_result - lfilt_result).max()\n",
    "    diff_list.append(diff)\n",
    "    \n",
    "    diff2 = np.abs(conv1d_result - lfilt_result).max()\n",
    "    diff2_list.append(diff2)\n",
    "    \n",
    "    diff3 = np.abs(npconv_result - lfilt_result).max()\n",
    "    diff3_list.append(diff3)\n",
    "    \n",
    "# Verify that np.convolve and lfilter gave the same results.\n",
    "print(\"Did np.convolve and lfilter produce the same results?\",)\n",
    "check = all(diff < 1e-13 for diff in diff3_list)\n",
    "if check:\n",
    "    print(\"Yes\")\n",
    "else:\n",
    "    print(\"No! Something went wrong.\")\n",
    "\n",
    "# Verify that fftconvolve and lfilter gave the same results.\n",
    "print(\"Did fftconvolve and lfilter produce the same results?\",)\n",
    "check = all(diff < 1e-13 for diff in diff_list)\n",
    "if check:\n",
    "    print(\"Yes.\")\n",
    "else:\n",
    "    print(\"No! Something went wrong.\")\n",
    "    \n",
    "# Verify that convlve1d and lfilter gave the same results.\n",
    "print(\"Did convlve1d and lfilter produce the same results?\",)\n",
    "check = all(diff2 < 1e-13 for diff2 in diff2_list)\n",
    "if check:\n",
    "    print(\"Yes.\")\n",
    "else:\n",
    "    print(\"No! Something went wrong.\")\n"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
